#include "CityBlocks.h"
#include "MainState.h"
#include "Building.h"
#include "EffectManager.h"
#include <queue>
#define _USE_MATH_DEFINES
#include <math.h>


void CityBlocks::CreateVTess(Terrain* t)
{
	m_VTess.CreateRandomPoints(t);
	std::vector<D3DXVECTOR2> v = m_VTess.GetPoints();

#ifndef VORONOI_DEBUG
	for(unsigned int i=0; i<v.size();++i)
	{
		Building* b =new Building;
		b->Generate(D3DXVECTOR3(v[i].x,0,v[i].y),D3DXVECTOR3(10,60,10));
		MainState::Instance()->addGameObject(b);
	}
#endif
	m_VTess.Divide();


#ifdef _DEBUG


	for(unsigned int i=0; i<v.size();++i)
	{
		LPD3DXMESH mesh;
		D3DXCreateSphere(TheD3DApp::Instance()->GetD3DDev(),1,5,5,&mesh,0);
		

#ifdef VORONOI_DEBUG
		
		wchar_t buf[100];
		wsprintf(buf,L"%d",i);

		HRESULT hr;
		HDC hdc;
		HFONT font;
		hdc=CreateCompatibleDC(NULL);

		font=CreateFont(80,         //Height
			0,          //Width
			0,          //Escapement
			0,          //Orientation
			FW_NORMAL,  //Weight
			false,      //Italic
			false,      //Underline
			false,      //Strikeout
			DEFAULT_CHARSET,//Charset 
			OUT_DEFAULT_PRECIS,  //Output Precision
			CLIP_DEFAULT_PRECIS, //Clipping Precision
			DEFAULT_QUALITY,     //Quality
			DEFAULT_PITCH|FF_DONTCARE, //Pitch and Family
			L"Arial");

		SelectObject(hdc, font);
		D3DXCreateText(TheD3DApp::Instance()->GetD3DDev(),hdc,buf,10,0.1,&mesh,0,0);
#endif
		GameObject* g = new GameObject(mesh);
		g->SetTexture(L"UV.jpg");
		g->SetScale(D3DXVECTOR3(5,5,5));
		g->SetPos(D3DXVECTOR3(v[i].x,0,v[i].y));
		m_pvSites.push_back(g);
		MainState::Instance()->addGameObject(g);
	}


	D3DV2SET n = m_VTess.GetNodes();
	for (D3DV2SET::iterator it = n.begin();it!=n.end();++it)
	{
		D3DXVECTOR2 pos =(*it);
		LPD3DXMESH mesh;
		D3DXCreateBox(TheD3DApp::Instance()->GetD3DDev(),1,1,1,&mesh,0);
		GameObject* c = new GameObject(mesh);
		c->SetPos(D3DXVECTOR3(pos.x,0,pos.y));
		m_pvNodes.push_back(c);
		MainState::Instance()->addGameObject(c);

	}
#endif

	//create the city block rendering stuff
	for(unsigned int i=0; i<v.size();++i)
	{

#ifdef VORONOI_DEBUG
			wchar_t buf[100];
			wsprintf(buf,L"New Poly ID: %d \n", i);
			OutputDebugString(buf);
#endif
		D3DXVECTOR2 side1;
		D3DXVECTOR2 side2;
		Graph* G = m_VTess.GetGraph();
		GraphNode* nearest;
		float dist=t->GetAbsSize();
		D3DXVECTOR2 vec;
		//find nearest node
		for (unsigned int j=0;j<G->GetNumNodes();j++)
		{
			vec = G->GetNode(j)->GetPos()-v[i];
			float c = sqrt((vec.x*vec.x)+(vec.y*vec.y));
			if(dist<c+0.001&&dist>c-0.001)//this is the tolerence value in the graph
			{
				MessageBox(0,L"2 possible 'nearest' nodes",L"Insufferable!",MB_OK);
			}
			if(dist>c)
			{
				dist=c;
				nearest=G->GetNode(j);
			}
		}

		std::vector<D3DXVECTOR3> edges;

		dist=t->GetAbsSize();
		vec=D3DXVECTOR2(0,0);
		int last = nearest->GetIndex();
		int cur = nearest->GetIndex();
		int next = -1;

		std::vector<int> visited;
		while(next!=nearest->GetIndex() && edges.size()<21)
		{
#ifdef VORONOI_DEBUG
			wchar_t buf[100];
			wsprintf(buf,L"Last: %d \n", cur);
			OutputDebugString(buf);
#endif
			visited.push_back(cur);
			edges.push_back(D3DXVECTOR3(G->GetNode(cur)->GetPos().x,0,G->GetNode(cur)->GetPos().y));
			std::list<GraphEdge> listGEs = m_VTess.GetGraph()->GetEdgeList(cur);
			std::queue<GraphNode*> poss;
			double BestAngle =360;
			double angle;

			side1=G->GetNode(cur)->GetPos()-v[i];
			for (std::list<GraphEdge>::iterator it = listGEs.begin();it!=listGEs.end();++it)
			{
#ifdef VORONOI_DEBUG
				wchar_t buf[100];
				wsprintf(buf,L"Candidate: %d \n", it->GetTo());
				OutputDebugString(buf);
#endif
				bool skip=false;
				if(it->GetTo()==nearest->GetIndex()&&last!=nearest->GetIndex())
				{
					skip=true;
					next=it->GetTo();
#ifdef VORONOI_DEBUG
					wchar_t buf[100];
					wsprintf(buf,L"Poly Complete! next = %d\n\n", next);
					OutputDebugString(buf);
#endif
					it=listGEs.end();
					it--;
				}
				if(it->GetTo()!=last && !skip)
				{

					//find angle between two vectors
					side2=G->GetNode(cur)->GetPos() - G->GetNode(it->GetTo())->GetPos();

					D3DXVec2Normalize(&side1,&side1);
					D3DXVec2Normalize(&side2,&side2);
					//angle = acos(D3DXVec2Dot(&side1,&side2))*(180/M_PI);

					angle = (atan2(side2.y,side2.x)-atan2(side1.y,side1.x))*(180/M_PI);
#ifdef VORONOI_DEBUG
					char buf[100];
					sprintf(buf,"angle = %f \n", angle);
					OutputDebugStringA(buf);
#endif
					if(angle<0)
					{
						angle+=360;
#ifdef VORONOI_DEBUG
						char buf[100];
						sprintf(buf,"correcting angle = %f \n", angle);
						OutputDebugStringA(buf);
#endif
					}
					if(angle==BestAngle)
					{
						MessageBox(0,L"The angles are equal!",L"Damn and Blast!",MB_OK);
					}
					if(angle==180)
					{
						MessageBox(0,L"Angle=180 exactly.",L"Paradoxical!",0);
					}
					if(angle<BestAngle && angle!=180)
					{
						BestAngle=angle;
						next = it->GetTo();
#ifdef VORONOI_DEBUG
						wchar_t buf[100];
						wsprintf(buf,L"Current Best: %d \n", next);
						OutputDebugString(buf);
#endif
					}


				}
				if(edges.size()>20)
				{
					wchar_t buf[100];
					wsprintf(buf,L"Too many edges in poly: %d \n", i);
					MessageBox(0,buf,L"Buggeration",MB_OK);
				}
				for (unsigned int i=1;i<visited.size();++i)
				{
					if(next==visited[i])
					{
						//MessageBox(0,L"Poly Loop Problem!",L"Buggeration",MB_OK);
					}
				}

			}

			/*
			for (std::list<GraphEdge>::iterator it = listGEs.begin();it!=listGEs.end();++it)
			{
			poss.push(G->GetNode(it->GetTo()));
			}
			dist=t->GetAbsSize();

			bool skip=false;
			while(!poss.empty())
			{
			for(unsigned int j=0;j<visited.size();++j)
			{
			if(poss.front()->GetIndex()==visited[j])
			{
			skip=true;
			}
			}
			if(!skip)
			{
			vec = poss.front()->GetPos()-v[i];
			float c = sqrt((vec.x*vec.x)+(vec.y*vec.y));
			if(dist>c)
			{
			dist=c;
			cur=poss.front()->GetIndex();
			}
			}
			poss.pop();

			}
			for (std::list<GraphEdge>::iterator it = listGEs.begin();it!=listGEs.end();++it)
			{
			if(G->GetNode(it->GetTo())->GetIndex()==nearest->GetIndex())
			{
			if(edges.size()>1)
			{
			cur=nearest->GetIndex();
			}
			}

			}
			if(cur==last)
			{
			for (std::list<GraphEdge>::iterator it = listGEs.begin();it!=listGEs.end();++it)
			{
			if(G->GetNode(it->GetTo())->GetIndex()==nearest->GetIndex())
			{
			cur=nearest->GetIndex();
			}
			}
			}
			*/

			last=cur;
			cur=next;

		}

		Block* b = new Block;

		b->Create(edges,D3DXVECTOR3(v[i].x,0,v[i].y));
		MainState::Instance()->addGameObject(b);

	}

	MainState::Instance()->addGameObject(m_VTess.GetGraph());
}


void CityBlocks::Render()
{
#ifdef _DEBUG

	for(unsigned int i=0;i<m_pvSites.size();++i)
	{
		m_pvSites[i]->SetDraw(m_bDraw);
	}
	for(unsigned int i=0;i<m_pvNodes.size();++i)
	{
		m_pvNodes[i]->SetDraw(m_bDraw);
	}

	if(m_bDraw)
	{

		VecLineSeg vls =  m_VTess.GetEdges();
		D3DXMATRIX mw,mv,mp,mvp;
		TheD3DApp::Instance()->GetD3DDev()->GetTransform(D3DTS_VIEW,&mv);
		TheD3DApp::Instance()->GetD3DDev()->GetTransform(D3DTS_PROJECTION,&mp);
		mvp= mv*mp;
		LPD3DXLINE l;
		D3DXCreateLine(TheD3DApp::Instance()->GetD3DDev(),&l);
		l->Begin();
		for (unsigned int i=0; i < vls.size();++i)
		{
			D3DXVECTOR3 points[2];
			points[0] = D3DXVECTOR3(vls[i].first.x,0,vls[i].first.y);
			points[1] = D3DXVECTOR3(vls[i].second.x,0,vls[i].second.y);


			l->DrawTransform(points,2,&mvp,D3DCOLOR_RGBA(0,255,0,255));

		}
		l->End();
	}
#endif
}